/******************************************************************************
 * * nv_api.c - implementation of nvram interface
 *
 * *(C) Copyright 2019 Asr International Ltd.
 * * All Rights Reserved
 * ******************************************************************************/
#include "ui_nvm.h"
#include "../../../lvgl/hal/hal.h"

/**
 * get section length from section id
 * param (in) SectionId:   UI_NV_SECTION_ID  section ID of NVM
 * return  UINT32:
 */
UINT32 UI_NV_Get_Section_Len(NV_UI_SECTION_ID SectionId)
{
    switch (SectionId)
    {
    case NV_SECTION_UI_FRAMEWORK:
        return(NV_SECTION_LEN(NV_SECTION_UI_FRAMEWORK));

    case NV_SECTION_UI_CALL:
        return(NV_SECTION_LEN(NV_SECTION_UI_CALL));

    case NV_SECTION_UI_CALL_LOG:
        return(NV_SECTION_LEN(NV_SECTION_UI_CALL_LOG));

    case NV_SECTION_UI_SETTINGS:
        return(NV_SECTION_LEN(NV_SECTION_UI_SETTINGS));

    case NV_SECTION_UI_CONTACTS_LIST:
        return(NV_SECTION_LEN(NV_SECTION_UI_CONTACTS_LIST));

    case NV_SECTION_UI_CONTACTS_BITMAP:
        return(NV_SECTION_LEN(NV_SECTION_UI_CONTACTS_BITMAP));

    case NV_SECTION_UI_SPEED_DIAL_LIST:
        return(NV_SECTION_LEN(NV_SECTION_UI_SPEED_DIAL_LIST));

    case NV_SECTION_UI_NUM_SCRN_LIST:
        return(NV_SECTION_LEN(NV_SECTION_UI_NUM_SCRN_LIST));

    case NV_SECTION_UI_ALARM:
        return(NV_SECTION_LEN(NV_SECTION_UI_ALARM));

    case NV_SECTION_UI_CALENDAR:
        return(NV_SECTION_LEN(NV_SECTION_UI_CALENDAR));

    case NV_SECTION_UI_SMS:
        return(NV_SECTION_LEN(NV_SECTION_UI_SMS));

    case NV_SECTION_UI_SMS_DIST_LIST:
        return(NV_SECTION_LEN(NV_SECTION_UI_SMS_DIST_LIST));

    case NV_SECTION_UI_SMS_DIST_CONT_LIST:
        return(NV_SECTION_LEN(NV_SECTION_UI_SMS_DIST_CONT_LIST));

    case NV_SECTION_UI_SMS_DRAFTS:
        return(NV_SECTION_LEN(NV_SECTION_UI_SMS_DRAFTS));

    case NV_SECTION_UI_AUDIO_PLAYER_MODE:
        return(NV_SECTION_LEN(NV_SECTION_UI_AUDIO_PLAYER_MODE));

    case NV_SECTION_UI_BLUETOOTH:
        return(NV_SECTION_LEN(NV_SECTION_UI_BLUETOOTH));

    default:
        printf("SectionId wrong\n");
        return(0);
    } /* switch */
}     /* UI_NV_Get_Section_Len */

/**
 * get file path of section
 * param (in) SectionId:   UI_NV_SECTION_ID  section ID of NVM
 * return  INT8*: file path
 */
INT8 *UI_NV_Get_Section_path(NV_UI_SECTION_ID SectionId)
{
    switch (SectionId)
    {
    case NV_SECTION_UI_FRAMEWORK:
        return(NV_SECTION_FILE_PATH(NV_SECTION_UI_FRAMEWORK));

    case NV_SECTION_UI_CALL:
        return(NV_SECTION_FILE_PATH(NV_SECTION_UI_CALL));

    case NV_SECTION_UI_CALL_LOG:
        return(NV_SECTION_FILE_PATH(NV_SECTION_UI_CALL_LOG));

    case NV_SECTION_UI_SETTINGS:
        return(NV_SECTION_FILE_PATH(NV_SECTION_UI_SETTINGS));

    case NV_SECTION_UI_CONTACTS_LIST:
        return(NV_SECTION_FILE_PATH(NV_SECTION_UI_CONTACTS_LIST));

    case NV_SECTION_UI_CONTACTS_BITMAP:
        return(NV_SECTION_FILE_PATH(NV_SECTION_UI_CONTACTS_BITMAP));

    case NV_SECTION_UI_SPEED_DIAL_LIST:
        return(NV_SECTION_FILE_PATH(NV_SECTION_UI_SPEED_DIAL_LIST));

    case NV_SECTION_UI_NUM_SCRN_LIST:
        return(NV_SECTION_FILE_PATH(NV_SECTION_UI_NUM_SCRN_LIST));

    case NV_SECTION_UI_ALARM:
        return(NV_SECTION_FILE_PATH(NV_SECTION_UI_ALARM));

    case NV_SECTION_UI_CALENDAR:
        return(NV_SECTION_FILE_PATH(NV_SECTION_UI_CALENDAR));

    case NV_SECTION_UI_SMS:
        return(NV_SECTION_FILE_PATH(NV_SECTION_UI_SMS));

    case NV_SECTION_UI_SMS_DIST_LIST:
        return(NV_SECTION_FILE_PATH(NV_SECTION_UI_SMS_DIST_LIST));

    case NV_SECTION_UI_SMS_DIST_CONT_LIST:
        return(NV_SECTION_FILE_PATH(NV_SECTION_UI_SMS_DIST_CONT_LIST));

    case NV_SECTION_UI_SMS_DRAFTS:
        return(NV_SECTION_FILE_PATH(NV_SECTION_UI_SMS_DRAFTS));

    case NV_SECTION_UI_AUDIO_PLAYER_MODE:
        return(NV_SECTION_FILE_PATH(NV_SECTION_UI_AUDIO_PLAYER_MODE));

    case NV_SECTION_UI_BLUETOOTH:
        return(NV_SECTION_FILE_PATH(NV_SECTION_UI_BLUETOOTH));
    default:
        printf("SectionId wrong\n");
        return(NULL);
    } /* switch */
}     /* UI_NV_Get_Section_Offset */

/**
 * reset nv to default value
 * param (in) SectionId:   UI_NV_SECTION_ID  section ID of NVM
 * return  UINT8: 1 means reset done, 0 means not reset
 */
UINT8 UI_NV_Reset_Default(NV_UI_SECTION_ID SectionId)
{
    char * TempData;
    uint32_t SectionLen = UI_NV_Get_Section_Len(SectionId);
    char FilePath[NV_MAX_SECTION_PATH_NAME];
    ui_file_t * pfile;
    NV_UI_Settings_t                       *Settings;
    NV_UI_Framework_t                      *Framework;
    NV_UI_Call_t                           *Call;
    NV_UI_Call_Log_t                       *CallLog;
    NV_UI_Contacts_Contact_List_t          *ContactList;
    NV_UI_Contacts_Bitmap_t                *ContactBitmap;
    NV_UI_Contacts_Speed_Dial_List_t       *SpeedDialList;
    NV_UI_Contacts_Num_Scrn_List_t         *NumScrnList;
    NV_UI_Alarm_t                          *Alarm;
    NV_UI_Calendar_t                       *Calendar;
    NV_UI_Sms_t                            *Sms;
    NV_UI_Sms_Distribution_List_t          *SmsDistriListInfo;
    NV_UI_Sms_Distribution_Contacts_List_t *SmsDistriContactList;
    NV_UI_Sms_Drafts_t                     *SmsDrafts;
    NV_UI_Audio_Player_t                   *AudioPlayerMode;
    NV_UI_Bluetooth_t                      *Bluetooth;

    switch(SectionId) {
        case NV_SECTION_UI_SETTINGS:
            Settings = lv_mem_alloc(SectionLen);
            memset(Settings, 0, SectionLen);
            Settings->DualSimSetting.DefaultSim4Standby = 1;
            Settings->DualSimSetting.SimName[0][0] = 's';
            Settings->DualSimSetting.SimName[0][1] = 'i';
            Settings->DualSimSetting.SimName[0][2] = 'm';
            Settings->DualSimSetting.SimName[0][3] = '1';
            Settings->DualSimSetting.SimName[1][0] = 's';
            Settings->DualSimSetting.SimName[1][1] = 'i';
            Settings->DualSimSetting.SimName[1][2] = 'm';
            Settings->DualSimSetting.SimName[1][3] = '2';

            Settings->ToneSetting.CurrentRingToneIndex[0] = 1;
            Settings->ToneSetting.CurrentRingToneIndex[1] = 1;
            Settings->ToneSetting.RingVolume = 5;
            Settings->ToneSetting.KeypadToneVolume = 5;
            Settings->ToneSetting.VibratingStat = 1;
            Settings->ToneSetting.MsgAlertStat[0] = 1;
            Settings->ToneSetting.MsgAlertStat[1] = 1;
            Settings->ToneSetting.CurrentMsgToneIndex[0] = 1;
            Settings->ToneSetting.CurrentMsgToneIndex[1] = 1;
            Settings->ToneSetting.WarningToneStat = 1;

            Settings->DisplaySetting.BacklightIntensity = 5;
            Settings->DisplaySetting.BacklightTimeout = 3;

            Settings->Profile_Setting.ProfileSetting[0].CurrentRingToneIndex[0] = 1;
            Settings->Profile_Setting.ProfileSetting[0].CurrentRingToneIndex[1] = 1;
            Settings->Profile_Setting.ProfileSetting[0].RingVolume = 5;
            Settings->Profile_Setting.ProfileSetting[0].KeypadToneVolume = 5;
            Settings->Profile_Setting.ProfileSetting[0].VibratingStat = 1;
            Settings->Profile_Setting.ProfileSetting[0].MsgAlertStat[0] = 1;
            Settings->Profile_Setting.ProfileSetting[0].MsgAlertStat[1] = 1;
            Settings->Profile_Setting.ProfileSetting[0].CurrentMsgToneIndex[0] = 1;
            Settings->Profile_Setting.ProfileSetting[0].CurrentMsgToneIndex[1] = 1;
            Settings->Profile_Setting.ProfileSetting[0].WarningToneStat = 1;
            Settings->Profile_Setting.ProfileSetting[1].CurrentRingToneIndex[0] = 1;
            Settings->Profile_Setting.ProfileSetting[1].CurrentRingToneIndex[1] = 1;
            Settings->Profile_Setting.ProfileSetting[1].VibratingStat = 1;
            Settings->Profile_Setting.ProfileSetting[2].CurrentRingToneIndex[0] = 1;
            Settings->Profile_Setting.ProfileSetting[2].CurrentRingToneIndex[1] = 1;
            Settings->Profile_Setting.ProfileSetting[2].RingVolume = 2;
            Settings->Profile_Setting.ProfileSetting[2].KeypadToneVolume = 2;
            Settings->Profile_Setting.ProfileSetting[2].VibratingStat = 1;
            Settings->Profile_Setting.ProfileSetting[2].MsgAlertStat[0] = 1;
            Settings->Profile_Setting.ProfileSetting[2].MsgAlertStat[1] = 1;
            Settings->Profile_Setting.ProfileSetting[2].CurrentMsgToneIndex[0] = 1;
            Settings->Profile_Setting.ProfileSetting[2].CurrentMsgToneIndex[1] = 1;
            Settings->Profile_Setting.ProfileSetting[2].WarningToneStat = 1;
            Settings->Profile_Setting.ProfileSetting[3].CurrentRingToneIndex[0] = 1;
            Settings->Profile_Setting.ProfileSetting[3].CurrentRingToneIndex[1] = 1;
            Settings->Profile_Setting.ProfileSetting[3].RingVolume = 7;
            Settings->Profile_Setting.ProfileSetting[3].KeypadToneVolume = 7;
            Settings->Profile_Setting.ProfileSetting[3].VibratingStat = 1;
            Settings->Profile_Setting.ProfileSetting[3].MsgAlertStat[0] = 1;
            Settings->Profile_Setting.ProfileSetting[3].MsgAlertStat[1] = 1;
            Settings->Profile_Setting.ProfileSetting[3].CurrentMsgToneIndex[0] = 1;
            Settings->Profile_Setting.ProfileSetting[3].CurrentMsgToneIndex[1] = 1;
            Settings->Profile_Setting.ProfileSetting[3].WarningToneStat = 1;
            Settings->Profile_Setting.ProfileSetting[4].CurrentRingToneIndex[0] = 1;
            Settings->Profile_Setting.ProfileSetting[4].CurrentRingToneIndex[1] = 1;
            Settings->Profile_Setting.ProfileSetting[4].RingVolume = 5;
            Settings->Profile_Setting.ProfileSetting[4].KeypadToneVolume = 5;
            Settings->Profile_Setting.ProfileSetting[4].VibratingStat = 1;
            Settings->Profile_Setting.ProfileSetting[4].MsgAlertStat[0] = 1;
            Settings->Profile_Setting.ProfileSetting[4].MsgAlertStat[1] = 1;
            Settings->Profile_Setting.ProfileSetting[4].CurrentMsgToneIndex[0] = 1;
            Settings->Profile_Setting.ProfileSetting[4].CurrentMsgToneIndex[1] = 1;
            Settings->Profile_Setting.ProfileSetting[4].WarningToneStat = 1;
            Settings->TimeSetting.TimeFormat = 1;
            Settings->TimeSetting.TimeDisplay = 1;
            Settings->TimeSetting.TimeAutoUpdate = 1;
            Settings->PhoneSetting.AutoGuardOn = 1;
            Settings->PhoneSetting.AutoGuardDelay = 30;
            //Settings->PhoneSetting.AutoGuardDelay = (Settings->PhoneSetting.AutoGuardDelay << 8) & 0xFF00;
            Settings->PhoneSetting.StartupToneOn = 1;
            Settings->PhoneSetting.WelcomeNoteOn = 1;
            Settings->PhoneSetting.WelcomeNote[0] = 'w';
            Settings->PhoneSetting.WelcomeNote[1] = 'e';
            Settings->PhoneSetting.WelcomeNote[2] = 'l';
            Settings->PhoneSetting.WelcomeNote[3] = 'c';
            Settings->PhoneSetting.WelcomeNote[4] = 'o';
            Settings->PhoneSetting.WelcomeNote[5] = 'm';
            Settings->PhoneSetting.WelcomeNote[6] = 'e';
            Settings->SecuritySetting.SecurityCode[0] = '1';
            Settings->SecuritySetting.SecurityCode[1] = '2';
            Settings->SecuritySetting.SecurityCode[2] = '3';
            Settings->SecuritySetting.SecurityCode[3] = '4';
            TempData = (char *)Settings;
            break;
        case NV_SECTION_UI_FRAMEWORK:
            Framework = lv_mem_alloc(SectionLen);
            memset(Framework, 0, SectionLen);
            Framework->AppNameTextId[0] = 4;
            //Framework->AppNameTextId[0] = (Framework->AppNameTextId[0] << 8) & 0xFF00;
            Framework->AppNameTextId[1] = 5;
            //Framework->AppNameTextId[1] = (Framework->AppNameTextId[1] << 8) & 0xFF00;
            Framework->AppNameTextId[2] = 10;
            //Framework->AppNameTextId[2] = (Framework->AppNameTextId[2] << 8) & 0xFF00;
            Framework->AppNameTextId[3] = 0xffff;
            Framework->AppNameTextId[4] = 3;
            //Framework->AppNameTextId[4] = (Framework->AppNameTextId[4] << 8) & 0xFF00;
            Framework->AppNameTextId[5] = 11;
            //Framework->AppNameTextId[5] = (Framework->AppNameTextId[5] << 8) & 0xFF00;
            Framework->AppNameTextId[6] = 9;
            //Framework->AppNameTextId[6] = (Framework->AppNameTextId[6] << 8) & 0xFF00;
            Framework->AppNameTextId[7] = 0xffff;
            Framework->AppNameTextId[8] = 0xffff;
            Framework->AppNameTextId[9] = 0xffff;
            Framework->AppNameTextId[10] = 0xffff;
            Framework->AppNameTextId[11] = 0xffff;
            Framework->AppNameTextId[12] = 0xffff;
            Framework->AppNameTextId[13] = 0xffff;
            Framework->AppNameTextId[14] = 0xffff;
            Framework->AppNameTextId[15] = 0xffff;
            Framework->AppNameTextId[16] = 0xffff;
            Framework->AppNameTextId[17] = 0xffff;
            Framework->AppNameTextId[18] = 0xffff;
            Framework->AppNameTextId[19] = 0xffff;
            TempData = (char *)Framework;
            break;
        case NV_SECTION_UI_CALL:
            Call = lv_mem_alloc(SectionLen);
            memset(Call, 0, SectionLen);
            Call->HandsetVolume = 5;
            Call->SpeakerVolume = 5;
            Call->EmergencyNumber.ENumberCnt = 2;
            Call->EmergencyNumber.ENumber[0][0] = '1';
            Call->EmergencyNumber.ENumber[0][1] = '1';
            Call->EmergencyNumber.ENumber[0][2] = '2';
            Call->EmergencyNumber.ENumber[1][0] = '1';
            Call->EmergencyNumber.ENumber[1][1] = '1';
            Call->EmergencyNumber.ENumber[1][2] = '9';
            TempData = (char *)Call;
            break;
        case NV_SECTION_UI_CALL_LOG:
            CallLog = lv_mem_alloc(SectionLen);
            memset(CallLog, 0, SectionLen);
            TempData = (char *)CallLog;
            break;
        case NV_SECTION_UI_CONTACTS_LIST:
            ContactList = lv_mem_alloc(SectionLen);
            memset(ContactList, 0, SectionLen);
            ContactList->ContactInfo[0].ToneIndex = 0xff;
            ContactList->ContactInfo[1].ToneIndex = 0xff;
            ContactList->ContactInfo[2].ToneIndex = 0xff;
            ContactList->ContactInfo[3].ToneIndex = 0xff;
            ContactList->ContactInfo[4].ToneIndex = 0xff;
            ContactList->ContactInfo[5].ToneIndex = 0xff;
            ContactList->ContactInfo[6].ToneIndex = 0xff;
            ContactList->ContactInfo[7].ToneIndex = 0xff;
            ContactList->ContactInfo[8].ToneIndex = 0xff;
            ContactList->ContactInfo[9].ToneIndex = 0xff;
            ContactList->ContactInfo[10].ToneIndex = 0xff;
            ContactList->ContactInfo[11].ToneIndex = 0xff;
            ContactList->ContactInfo[12].ToneIndex = 0xff;
            ContactList->ContactInfo[13].ToneIndex = 0xff;
            ContactList->ContactInfo[14].ToneIndex = 0xff;
            ContactList->ContactInfo[15].ToneIndex = 0xff;
            ContactList->ContactInfo[16].ToneIndex = 0xff;
            ContactList->ContactInfo[17].ToneIndex = 0xff;
            ContactList->ContactInfo[18].ToneIndex = 0xff;
            ContactList->ContactInfo[19].ToneIndex = 0xff;
            ContactList->ContactInfo[20].ToneIndex = 0xff;
            ContactList->ContactInfo[21].ToneIndex = 0xff;
            ContactList->ContactInfo[22].ToneIndex = 0xff;
            ContactList->ContactInfo[23].ToneIndex = 0xff;
            ContactList->ContactInfo[24].ToneIndex = 0xff;
            ContactList->ContactInfo[25].ToneIndex = 0xff;
            ContactList->ContactInfo[26].ToneIndex = 0xff;
            ContactList->ContactInfo[27].ToneIndex = 0xff;
            ContactList->ContactInfo[28].ToneIndex = 0xff;
            ContactList->ContactInfo[29].ToneIndex = 0xff;
            TempData = (char *)ContactList;
            break;
        case NV_SECTION_UI_CONTACTS_BITMAP:
            ContactBitmap = lv_mem_alloc(SectionLen);
            memset(ContactBitmap, 0, SectionLen);
            TempData = (char *)ContactBitmap;
            break;
        case NV_SECTION_UI_SPEED_DIAL_LIST:
            SpeedDialList = lv_mem_alloc(SectionLen);
            memset(SpeedDialList, 0, SectionLen);
            TempData = (char *)SpeedDialList;
            break;
        case NV_SECTION_UI_NUM_SCRN_LIST:
            NumScrnList = lv_mem_alloc(SectionLen);
            memset(NumScrnList, 0, SectionLen);
            TempData = (char *)NumScrnList;
            break;
        case NV_SECTION_UI_ALARM:
            Alarm = lv_mem_alloc(SectionLen);
            memset(Alarm, 0, SectionLen);
            TempData = (char *)Alarm;
            break;
        case NV_SECTION_UI_CALENDAR:
            Calendar = lv_mem_alloc(SectionLen);
            memset(Calendar, 0, SectionLen);
            TempData = (char *)Calendar;
            break;
        case NV_SECTION_UI_SMS:
            Sms = lv_mem_alloc(SectionLen);
            memset(Sms, 0, SectionLen);
            TempData = (char *)Sms;
            break;
        case NV_SECTION_UI_SMS_DIST_LIST:
            SmsDistriListInfo = lv_mem_alloc(SectionLen);
            memset(SmsDistriListInfo, 0, SectionLen);
            TempData = (char *)SmsDistriListInfo;
            break;
    case NV_SECTION_UI_SMS_DIST_CONT_LIST:
            SmsDistriContactList = lv_mem_alloc(SectionLen);
            memset(SmsDistriContactList, 0, SectionLen);
            TempData = (char *)SmsDistriContactList;
            break;
    case NV_SECTION_UI_SMS_DRAFTS:
            SmsDrafts = lv_mem_alloc(SectionLen);
            memset(SmsDrafts, 0, SectionLen);
            TempData = (char *)SmsDrafts;
            break;
    case NV_SECTION_UI_AUDIO_PLAYER_MODE:
            AudioPlayerMode = lv_mem_alloc(SectionLen);
            memset(AudioPlayerMode, 0, SectionLen);
            TempData = (char *)AudioPlayerMode;
            break;
    case NV_SECTION_UI_BLUETOOTH:
            Bluetooth = lv_mem_alloc(SectionLen);
            memset(Bluetooth, 0, SectionLen);
            TempData = (char *)Bluetooth;
            break;
        default:
            TempData = NULL;
            break;
    }

    snprintf(FilePath, NV_MAX_SECTION_PATH_NAME, "%s%s", NV_SECTION_ROOT_DIR, UI_NV_Get_Section_path(SectionId));
    UI_FILE_REMOVE(FilePath);
    pfile = UI_FILE_OPEN((const char *)FilePath, UI_FILE_WRITE_ONLY);
    UI_FILE_WRITE(pfile, TempData, SectionLen);                                                          // write to operate file
    UI_FILE_CLOSE(pfile);
    lv_mem_free(TempData);
    return (1);
}

/**
 * write to file
 * param (in) SectionId:   UI_NV_SECTION_ID  section ID of NVM
 * param (in) Offset:  uint32_t                Offset in the Section
 * param (in) Len:   uint32_t                  Length of data to read
 * param (out) Data:  uint32_t*                data buffer
 * return  uint32_t: bytes have been writen
 */
uint32_t UI_NV_Write_Req(NV_UI_SECTION_ID SectionId, uint32_t Offset, uint32_t Len, uint8_t * Data)
{
    uint32_t    WriteLen = 0;
    ui_file_t * pfile;
    uint32_t    SectionLen;
    char      FilePath[NV_MAX_SECTION_PATH_NAME];

    SectionLen = UI_NV_Get_Section_Len(SectionId);

    if(SectionLen < (Offset + Len)) {
        printf("Len of Section is %d, offset + len = %d is too big\n",
               SectionLen,
               Offset + Len);
        return(0);
    }

    // get full file path
    snprintf(FilePath, NV_MAX_SECTION_PATH_NAME, "%s%s", NV_SECTION_ROOT_DIR, UI_NV_Get_Section_path(SectionId));

    pfile = UI_FILE_OPEN((const char *)FilePath, UI_FILE_RD_APPEND);
    if(NULL == pfile->file_d) {
        printf("please check file path\n");
        UI_NV_Reset_Default(SectionId);
        return(0);
    }

    UI_FILE_SEEK(pfile, Offset);                        // write nv data
    WriteLen = UI_FILE_WRITE(pfile, Data, Len);
    if(0 == WriteLen) {
        printf("write in fs is wrong, return default valure\n");
        return(0);
    }
    UI_FILE_CLOSE(pfile);
    return(Len);
} /* UI_NV_Write_Req */

/**
 * read data from NVRAM
 * param (in) SectionId:   UI_NV_SECTION_ID  section ID of NVM
 * param (in) Offset:  uint32_t                Offset in the Section
 * param (in) len:   uint32_t                  Length of data to read
 * param (out) data:  uint32_t*                data buffer
 * return  uint32_t: bytes have been read
 */
uint32_t UI_NV_Read_Req(NV_UI_SECTION_ID SectionId, uint32_t Offset, uint32_t Len, uint8_t * Data)
{
    uint32_t    ReadLen = 0;
    ui_file_t * pfile;
    uint32_t    SectionLen = UI_NV_Get_Section_Len(SectionId);
    char      FilePath[NV_MAX_SECTION_PATH_NAME] = {0};

    if(SectionLen < (Offset + Len)) {
        printf("len of section is %d, offset + len = %d is too big\n",
               SectionLen,
               Offset + Len);
        return(ReadLen);
    }

    // get full file path
    snprintf(FilePath, NV_MAX_SECTION_PATH_NAME, "%s%s", NV_SECTION_ROOT_DIR, UI_NV_Get_Section_path(SectionId));
    pfile = UI_FILE_OPEN((const char *)FilePath, UI_FILE_RD_APPEND);
    if(NULL == pfile->file_d) {
        printf("please check file path\n");
    } else {
        UI_FILE_SEEK(pfile, Offset);                // read data
        ReadLen = UI_FILE_READ(pfile, Data, Len);
        UI_FILE_CLOSE(pfile);
    }

    if(0 == ReadLen) {
        printf("read in fs is wrong return default value\n");
        if(1 == UI_NV_Reset_Default(SectionId)) {
            pfile = UI_FILE_OPEN((const char *)FilePath, UI_FILE_RD_APPEND);
            if(NULL == pfile->file_d) {
                printf("please check file path\n");
                return(0);
            }

            UI_FILE_SEEK(pfile, Offset);                // read data
            ReadLen = UI_FILE_READ(pfile, Data, Len);
            UI_FILE_CLOSE(pfile);
        }
    }
    return(Len);
} /* UI_NV_Read_Req */

/**
 * write default value to NVRAM for factory restore
 * return  void:
 */
VOID UI_NV_Restroe_Req(VOID)
{
    uint8_t i;
    ui_file_t * pfile;
    char      FilePath[NV_MAX_SECTION_PATH_NAME];
    // read default nvm file
    for(i = 0; i < NV_SECTION_UI_MAX_NUM; i++) {
        // section before this has default value,open default nv file
        snprintf(FilePath, NV_MAX_SECTION_PATH_NAME, "%s%s", NV_SECTION_ROOT_DIR, UI_NV_Get_Section_path(i));
        pfile = UI_FILE_OPEN((const char *)FilePath, UI_FILE_READ_ONLY);
        if(NULL == pfile->file_d) {
            UI_NV_Reset_Default(i);
        }
        UI_FILE_CLOSE(pfile);
    }       
}
